#coding:utf8
import os
import re
import codecs

#未知Tag 跳过相应的数据部分
classTem = '''
Require("CommonScript/AutoChess/Buffer.lua")
local SetIndex = Lib.SetIndex
local WriteBuffer= Lib.WriteBuffer

local %s = {}
Lib.Protos.%s = %s

function %s:Parse(buffer)
	while true do
		local tag, ty = buffer:ReadTagAndType()
		if tag == 0 then
			return
%s
		else
			buffer:DefaultRead(tag, ty)
		end
	end
end

function %s:Serialize(shareBuff)
	local buf = {}
	SetIndex(buf, WriteBuffer)
	buf:Init(shareBuff)

	%s
	return buf
end

%s.DefaultV = {
%s
}
function %s:SetDefault()
	Lib:DefaultInitTb(self, %s.DefaultV)
end
'''

EmptyMapInit = '''
	self.%s = {}
'''

unIntTem = '''
		elseif tag == %d then
			self.%s = buffer:ReadUnSignedInt()
'''

intTem = '''
		elseif tag == %d then
			self.%s = buffer:ReadInt()
'''

stringTem = '''
		elseif tag == %d then
			self.%s = buffer:ReadString()
'''

boolTem = '''
		elseif tag == %d then
			self.%s = buffer:ReadBool()
'''

messageTem = '''
		elseif tag == %d then
			local msgObj = {}
			SetIndex(msgObj, %s)
			self.%s = buffer:ReadMsg(msgObj)
'''


repeatedTem = '''
		elseif tag == %d then
			if self.%s == nil then
				self.%s = {}
			end
			%s
			table.insert(self.%s, temp)
'''

repeatedMapRead = '''
		elseif tag == %d then
			if self.%s == nil then
				self.%s = {}
			end
			%s
			self.%s[key] = value
'''

repeatedMapReadBody = '''
			local msgObj = {}
			SetIndex(msgObj, %s)
			local temp = buffer:ReadMsg(msgObj)
			local key = temp.key
			local value = temp.value
'''

repeatedUnInt = '''
			local temp = buffer:ReadUnSignedInt()
'''

repeatedInt = '''
			local temp = buffer:ReadInt()
'''
repeatedStr = '''
			local temp = buffer:ReadString()
'''
repeatedBool = '''
			local temp = buffer:ReadBool()
'''
repeatedMsg = '''
			local msgObj = {}
			SetIndex(msgObj, %s)
			local temp = buffer:ReadMsg(msgObj)
'''


wIntTem = '''
	if self.%s ~= nil then
		buf:WriteInt(%d, self.%s)
	end
'''

wUnIntTem = '''
	if self.%s ~= nil then
		buf:WriteUnSignedInt(%d, self.%s)
	end
'''

wBoolTem = '''
	if self.%s ~= nil then
		buf:WriteBool(%d, self.%s)
	end
'''
wStrTem = '''
	if self.%s ~= nil then
		buf:WriteString(%d, self.%s)
	end
'''
wMsgTem = '''
	if self.%s ~= nil then
		SetIndex(self.%s, %s)
		buf:WriteMsg(%d, self.%s)
	end
'''

repeatedWrite = '''
	if self.%s ~= nil then
		for k, v in ipairs(self.%s) do
			%s
		end
	end
'''

rWUnInt = '''
			buf:WriteUnSignedInt(%d, v)
'''

rWInt = '''
			buf:WriteInt(%d, v)
'''
rwBool = '''
			buf:WriteBool(%d, v)
'''
rWStr = '''
			buf:WriteString(%d, v)
'''

rWMsg = '''
			SetIndex(v, %s)
			buf:WriteMsg(%d, v)
'''

#支持MapField_XXX
#for k, v in pairs(self.tbItemInfo) do
#
#end
repeatedMap = '''
	if self.%s ~= nil then
		for k, v in pairs(self.%s) do
			%s
		end
	end
'''
rWMap = '''
			local mapEntity = {key = k, value = v}
			SetIndex(mapEntity, %s)
			buf:WriteMsg(%d, mapEntity)
'''


begin = re.compile("\s*message\s*(\w+)\s*\{")
field = re.compile("\s*(optional|required|repeated)\s*(uint64|string|bool|int32|\w+)\s*(\w+)\s*=\s*(\d+)")
end = re.compile("\s*\}")

codes = []

def GenCode(result):
	#f = open(result["type"]+".lua", "w")
	s = ""
	field = ""
	emptyInitInfo = ""
	for fi in result["field"]:
		tp = fi[1] #类型  repeated MapField_IB TakedReward = 4
		fn = fi[2] #fieldName
		fid = int(fi[3])
		if tp.find("MapField") != -1 and fi[0] != "repeated":
			print("Error: MapField Should Use repeated", tp, fi)
		if fi[0] == "repeated":
			isMapType = False
			#初始化数组
			emptyInitInfo += EmptyMapInit % (fn)
			temp = ""
			if tp == "uint64":
				temp = repeatedUnInt
			elif tp == "int32":
				temp = repeatedInt
			elif tp == "string":
				temp = repeatedStr
			elif tp == "bool":
				temp = repeatedBool
			elif tp.find("MapField") != -1:
				isMapType = True
				temp = repeatedMapReadBody % (tp)
			else:
				temp = repeatedMsg % (tp)
			if not isMapType:
				field += repeatedTem % (fid, fn, fn, temp, fn)
			else:
				field += repeatedMapRead % (fid, fn, fn, temp, fn)

		else:
			if tp == "uint64":
				field += unIntTem % (fid, fi[2])
			elif tp == "int32":
				field += intTem % (fid, fi[2])
			elif tp == "string":
				field += stringTem % (fid, fi[2])
			elif tp == "bool":
				field += boolTem % (fid, fi[2])
			else:
				field += messageTem % (fid, tp, fi[2])


	wfield = ""
	for fi in result["field"]:
		tp = fi[1]
		fid = int(fi[3])
		fn = fi[2]

		if tp.find("MapField") != -1 and fi[0] != "repeated":
			print("Error: MapField Should Use repeated", tp, fi)

		if fi[0] == "repeated":
			isMapType = False

			temp = ""
			if tp == "uint64":
				temp = rWUnInt % (fid)
			elif tp == "int32":
				temp = rWInt % (fid)
			elif tp == "string":
				temp = rWStr % (fid)
			elif tp == "bool":
				temp = rwBool % (fid)
			elif tp.find("MapField") != -1:
				isMapType = True
				temp = rWMap % (tp, fid)
			else:
				temp = rWMsg % (tp, fid)
			if not isMapType:
				wfield += repeatedWrite % (fn, fn, temp)
			else:
				wfield += repeatedMap % (fn, fn, temp)
		else:
			if tp == "uint64":
				wfield += wUnIntTem % (fn, fid, fn)
			elif tp == "int32":
				wfield += wIntTem % (fn, fid, fn)
			elif tp == "string":
				wfield += wStrTem % (fn, fid, fn)
			elif tp == "bool":
				wfield += wBoolTem % (fn, fid, fn)
			else:
				wfield += wMsgTem % (fn, fn, tp, fid, fn)

	#默认Field初始化
	defaultField = ""
	for fi in result["field"]:
		tp = fi[1] #类型  repeated MapField_IB TakedReward = 4
		fn = fi[2] #fieldName
		fid = int(fi[3])
		if fi[0] == "repeated":
			defaultField += "%s = {},\n" % (fn)
		else:
			if tp == "uint64":
				defaultField += "%s = 0,\n" % (fn)
			elif tp == "int32":
				defaultField += "%s = 0,\n" % (fn)
			elif tp == "string":
				defaultField += "%s = \"\",\n" % (fn)
			elif tp == "bool":
				defaultField += "%s = false,\n" % (fn)
			elif tp == "bool":
				defaultField += "%s = {},\n" % (fn)

	ct = classTem % (result["type"], result["type"], result["type"], result["type"], field, 
	result["type"], wfield, 
		result["type"], defaultField,
		result["type"], result["type"])
	codes.append(ct)
	#f.write(ct)
	#f.close()

def HandleFile(f):
	lines = codecs.open(f, "r", encoding="utf8").readlines()
	state = 0
	curType = ''
	result = {}
	for l in lines:
		if state == 0:
			mat = begin.findall(l)
			if len(mat) > 0:
				curType = mat[0]
				state = 1
				print(curType)
				result = {}
				result["type"] = curType
				result["field"] = []
		elif state == 1:
			mat = field.findall(l)
			if len(mat) > 0:
				curFiled = mat[0]
				print(curFiled)
				result["field"].append(curFiled)
			else:
				mat = end.findall(l)
				if len(mat) > 0:
					state = 0
					GenCode(result)


def GenFile():
	f = open("../CommonScript/AutoChess/PBCode.lua", "w")
	for ct in codes:
		f.write(ct)
	f.close()

def main():
	#HandleFile("test1.proto")
	#测试repeated
	HandleFile("delta.proto")

	GenFile()
main()